/**********************************************************************************
 * 文件名称：usr_tmr.c
 * 功能说明：定时器任务处理函数
 * 作者：（qq：554163925）
 * 修改记录
 * 1、在goly-subscribe基础上新建
 * 2、实际应用
 * 	  声明：
 *	  static tmr_t *tmrRealTimeSender = NULL;
 *	  static void led_toggle(uint8_t ID)
 * 
 *    创建新任务
 *	  if(NULL == tmrRealTimeSender ){
 *			tmrRealTimeSender = TMR_Subscribe(true,10,TMR_TYPE_10MS,(tmr_procTriggerHdlr_t)led_toggle);
 *	  }
 *
 *	  注销任务
 *	  if(tmrRealTimeSender){
 *			TMR_UnSubscribe ( tmrRealTimeSender, ( tmr_procTriggerHdlr_t )led_toggle, TMR_TYPE_10MS );
 *			tmrRealTimeSender = NULL;
 *	  }
 *
 * 3、在systick中断里里增加
 *	while (SysTick_Config(SystemCoreClock/1000));		//创建1ms中断一次
 *
 *	StyticNum++;
 *	if(StyticNum%100==0){	
 *		StyticNum = 0;
 *		TMR_100msUpdateRequest();
 *	}
 *
**********************************************************************************/
#include "usr_tmr.h"
#include <string.h>



/* 定义定时器配置 */
static TMR_IfTypedef Timer = { 0, {false}, {0}, {0} };

/* 定义定时器数量 */
static volatile uint8_t  Tmr10msCounter = 0;
static volatile uint8_t  Tmr100msCounter = 0;


/*
 **********************************************************************************
 *	函 数 名: TMR_Subscribe
 *	功能说明: 定时器接口初始化
 *	形     参:  cyclic : 		是否循环定时器
 *			  TimerValue ： 定时间隔
 *			  TimerType ：	定时器类型
 * 			  Timerhdlr ：	定时器响应处理机
 *	返 回 值: 定时器句柄
 **********************************************************************************
*/ 
tmr_t *TMR_Subscribe ( bool cyclic, uint32_t TimerValue, uint8_t TimerType, tmr_procTriggerHdlr_t Timerhdlr )
{
	#if OS_CRITICAL_METHOD == 3            /* Allocate storage for CPU status register */
		OS_CPU_SR  cpu_sr = 0;
	#endif

	switch ( TimerType )
	{
		case TMR_TYPE_10MS:
			if ( Timerhdlr && ( TimerValue > 0 ) )
			{
				if ( Timer.tmr_nbr < TMR_ID_COUNT )
				{
					uint32_t i;

					for ( i = 0; i < TMR_ID_COUNT; i++ )
					{
						if ( Timer.tmr_alloc[ i ].TimerId == 0 )
						{
//							OS_ENTER_CRITICAL ();
							Timer.tmr_cyclic[ i ] = cyclic;
							Timer.tmr_alloc[ i ].TimerId    = ++Timer.tmr_nbr;
							Timer.tmr_alloc[ i ].TimerType  = TMR_TYPE_10MS;
							Timer.tmr_alloc[ i ].TimerValue = TimerValue;
							Timer.tmr_alloc[ i ].TimerHdlr  = ( tmr_procTriggerHdlr_t )Timerhdlr;
							Timer.tmr_count[ i ] = Timer.tmr_alloc[ i ].TimerValue;
							Tmr10msCounter++;
//							OS_EXIT_CRITICAL ();

						#if TMR_INFO_DEBUG == 1
							printf ( "\r\n[TMR EVENT] id %u cyclic %s, time %u (10ms), total tmr %u\r\n", 
							Timer.tmr_alloc[ i ].TimerId, ( cyclic ? "TRUE" : "false" ), Timer.tmr_alloc[ i ].TimerValue, Timer.tmr_nbr );
						#endif  /* TMR_INFO_DEBUG */

							return ( tmr_t * )&Timer.tmr_alloc[ i ];            
						}
					}
				}

				#if TMR_INFO_DEBUG == 1
				else
				{
					printf ( "\r\n[TMR EVENT] err no timer resource***\r\n" );
				}
				#endif  /* TMR_INFO_DEBUG */

			}

			#if TMR_INFO_DEBUG == 1
			else
			{
			printf ( "\r\n[TMR EVENT] err TimerValue or Timerhdlr***\r\n" );
			}
			#endif  /* TMR_INFO_DEBUG */
		break;

		case TMR_TYPE_100MS:
			if ( Timerhdlr && ( TimerValue > 0 ) )
			{
				if ( Timer.tmr_nbr < TMR_ID_COUNT )
				{
					uint32_t i;

					for ( i = 0; i < TMR_ID_COUNT; i++ )
					{
						if ( Timer.tmr_alloc[ i ].TimerId == 0 )
						{
//							OS_ENTER_CRITICAL ();
							Timer.tmr_cyclic[ i ] = cyclic;
							Timer.tmr_alloc[ i ].TimerId	= ++Timer.tmr_nbr;
							Timer.tmr_alloc[ i ].TimerType	= TMR_TYPE_100MS;
							Timer.tmr_alloc[ i ].TimerValue = TimerValue;
							Timer.tmr_alloc[ i ].TimerHdlr	= ( tmr_procTriggerHdlr_t )Timerhdlr;
							Timer.tmr_count[ i ] = Timer.tmr_alloc[ i ].TimerValue;
							Tmr100msCounter++;
//							OS_EXIT_CRITICAL ();

						#if TMR_INFO_DEBUG == 1
							printf ( "\r\n[TMR EVENT] id %u cyclic %s, time %u (100ms), total tmr %u\r\n", 
							Timer.tmr_alloc[ i ].TimerId, ( cyclic ? "TRUE" : "false" ), Timer.tmr_alloc[ i ].TimerValue, Timer.tmr_nbr );
						#endif  /* TMR_INFO_DEBUG */

							return ( tmr_t * )&Timer.tmr_alloc[ i ];			
						}
					}
				}

				#if TMR_INFO_DEBUG == 1
				else
				{
					printf ( "\r\n[TMR EVENT] err no timer resource***\r\n" );
				}
				#endif  /* TMR_INFO_DEBUG */
			}

			#if TMR_INFO_DEBUG == 1
			else
			{
				printf ( "\r\n[TMR EVENT] err TimerValue or Timerhdlr***\r\n" );
			}
			#endif  /* TMR_INFO_DEBUG */
		break;


		case TMR_TYPE_TICK:
			if ( Timerhdlr && ( TimerValue > 0 ) )
			{
				if ( Timer.tmr_nbr < TMR_ID_COUNT )
				{
					uint32_t i;

					for ( i = 0; i < TMR_ID_COUNT; i++ )
					{
						if ( Timer.tmr_alloc[ i ].TimerId == 0 )
						{
//							OS_ENTER_CRITICAL ();
							Timer.tmr_cyclic[ i ] = cyclic;
							Timer.tmr_alloc[ i ].TimerId    = ++Timer.tmr_nbr;
							Timer.tmr_alloc[ i ].TimerType  = TMR_TYPE_TICK;
							Timer.tmr_alloc[ i ].TimerValue = TimerValue;
							Timer.tmr_alloc[ i ].TimerHdlr  = ( tmr_procTriggerHdlr_t )Timerhdlr;
							Timer.tmr_count[ i ] = Timer.tmr_alloc[ i ].TimerValue;
							Tmr10msCounter++;
//							OS_EXIT_CRITICAL ();

							#if TMR_INFO_DEBUG == 1
								printf ( "\r\n[TMR EVENT] id %u cyclic %s, time %u (10ms), total tmr %u\r\n", 
								Timer.tmr_alloc[ i ].TimerId, ( cyclic ? "TRUE" : "false" ), Timer.tmr_alloc[ i ].TimerValue, Timer.tmr_nbr );
							#endif  /* TMR_INFO_DEBUG */

							return ( tmr_t * )&Timer.tmr_alloc[ i ];            
						}
					}
				}

				#if TMR_INFO_DEBUG == 1
				else
				{
				printf ( "\r\n[TMR EVENT] err no timer resource***\r\n" );
				}
				#endif  /* TMR_INFO_DEBUG */

			}

			#if TMR_INFO_DEBUG == 1
			else
			{
				printf ( "\r\n[TMR EVENT] err TimerValue or Timerhdlr***\r\n" );
			}
			#endif  /* TMR_INFO_DEBUG */
		break;

		default:  break;
	}
	return NULL;
}


/*
 **********************************************************************************
 *	函 数 名: TMR_UnSubscribe
 *	功能说明: 定时器注销接口
 *	形     参:  tmr : 		定时器句柄
 *			  Timerhdlr ： 	定时器响应处理机
 *			  TimerType ：	定时器响应处理机
 *	返 回 值: 状态码
 **********************************************************************************
*/ 
bool TMR_UnSubscribe ( tmr_t *tmr, tmr_procTriggerHdlr_t Timerhdlr, uint8_t TimerType )
{
	#if OS_CRITICAL_METHOD == 3          /* Allocate storage for CPU status register */
	OS_CPU_SR  cpu_sr = 0;
	#endif

	switch ( TimerType )
	{
		case TMR_TYPE_10MS:
			if ( tmr && Timerhdlr )
			{
				uint32_t i;

				for ( i = 0; ( i < TMR_ID_COUNT ) && ( Timer.tmr_nbr > 0 ) && ( Tmr10msCounter > 0 ); i++ )
				{
					if ( ( Timer.tmr_alloc[ i ].TimerHdlr == ( tmr_procTriggerHdlr_t )Timerhdlr ) 
					&& ( Timer.tmr_alloc[ i ].TimerType == TMR_TYPE_10MS )
					&& ( ( tmr_t * )&Timer.tmr_alloc[ i ] == tmr )
					&& ( Timer.tmr_alloc[ i ].TimerId > 0 ) )
					{
//						OS_ENTER_CRITICAL ();
						Timer.tmr_nbr--;
						Timer.tmr_cyclic[ i ] = false;
						Timer.tmr_alloc[ i ].TimerId    = 0;
						Timer.tmr_alloc[ i ].TimerType  = TMR_TYPE_10MS;
						Timer.tmr_alloc[ i ].TimerValue = 0;
						Timer.tmr_alloc[ i ].TimerHdlr  = ( tmr_procTriggerHdlr_t )NULL;
						Timer.tmr_count[ i ] = 0;
						Tmr10msCounter--;
//						OS_EXIT_CRITICAL ();

						#if TMR_INFO_DEBUG == 1
							printf ( "\r\n[TMR EVENT] tmr left %u, released %u (10ms)\r\n", Timer.tmr_nbr, i );
						#endif  /* TMR_INFO_DEBUG */

						return true;            
					}
				}

				#if TMR_INFO_DEBUG == 1
					{
					printf ( "\r\n[TMR EVENT] tmr left %u, no tmr released\r\n", Timer.tmr_nbr );        
					}
				#endif  /* TMR_INFO_DEBUG */
			} 

			#if TMR_INFO_DEBUG == 1
			else
			{
				printf ( "\r\n[TMR EVENT] err tmr released***\r\n" );      
			}
			#endif  /* TMR_INFO_DEBUG */
		break;

		case TMR_TYPE_100MS:
			if ( tmr && Timerhdlr )
			{
				uint32_t i;

				for ( i = 0; ( i < TMR_ID_COUNT ) && ( Timer.tmr_nbr > 0 ) && ( Tmr100msCounter > 0 ); i++ )
				{
					if ( ( Timer.tmr_alloc[ i ].TimerHdlr == ( tmr_procTriggerHdlr_t )Timerhdlr ) 
					&& ( Timer.tmr_alloc[ i ].TimerType == TMR_TYPE_100MS )
					&& ( ( tmr_t * )&Timer.tmr_alloc[ i ] == tmr )
					&& ( Timer.tmr_alloc[ i ].TimerId > 0 ) )
					{
//						OS_ENTER_CRITICAL ();
						Timer.tmr_nbr--;
						Timer.tmr_cyclic[ i ] = false;
						Timer.tmr_alloc[ i ].TimerId	= 0;
						Timer.tmr_alloc[ i ].TimerType	= TMR_TYPE_100MS;
						Timer.tmr_alloc[ i ].TimerValue = 0;
						Timer.tmr_alloc[ i ].TimerHdlr	= ( tmr_procTriggerHdlr_t )NULL;
						Timer.tmr_count[ i ] = 0;
						Tmr100msCounter--;
//						OS_EXIT_CRITICAL ();

				#if TMR_INFO_DEBUG == 1
							printf ( "\r\n[TMR EVENT] tmr left %u, released %u (100ms)\r\n", Timer.tmr_nbr, i );
				#endif  /* TMR_INFO_DEBUG */

						return true;			
					}
				}

			#if TMR_INFO_DEBUG == 1
				{
				printf ( "\r\n[TMR EVENT] tmr left %u, no tmr released\r\n", Timer.tmr_nbr );		 
				}
			#endif  /* TMR_INFO_DEBUG */
			} 

			#if TMR_INFO_DEBUG == 1
				else
				{
					printf ( "\r\n[TMR EVENT] err tmr released***\r\n" );	   
				}
			#endif  /* TMR_INFO_DEBUG */
		break;


		case TMR_TYPE_TICK:
			if ( tmr && Timerhdlr )
			{
				uint32_t i;

				for ( i = 0; ( i < TMR_ID_COUNT ) && ( Timer.tmr_nbr > 0 ) && ( Tmr10msCounter > 0 ); i++ )
				{
					if ( ( Timer.tmr_alloc[ i ].TimerHdlr == ( tmr_procTriggerHdlr_t )Timerhdlr )
					&& ( Timer.tmr_alloc[ i ].TimerType == TMR_TYPE_TICK )
					&& ( ( tmr_t * )&Timer.tmr_alloc[ i ] == tmr )
					&& ( Timer.tmr_alloc[ i ].TimerId > 0 ) )
					{
//						OS_ENTER_CRITICAL ();
						Timer.tmr_nbr--;
						Timer.tmr_cyclic[ i ] = false;
						Timer.tmr_alloc[ i ].TimerId    = 0;
						Timer.tmr_alloc[ i ].TimerType  = TMR_TYPE_TICK;
						Timer.tmr_alloc[ i ].TimerValue = 0;
						Timer.tmr_alloc[ i ].TimerHdlr  = ( tmr_procTriggerHdlr_t )NULL;
						Timer.tmr_count[ i ] = 0;
						Tmr10msCounter--;
//						OS_EXIT_CRITICAL ();

						#if TMR_INFO_DEBUG == 1
							printf ( "\r\n[TMR EVENT] tmr left %u, released %u (10ms)\r\n", Timer.tmr_nbr, i );
						#endif  /* TMR_INFO_DEBUG */

						return true;            
					}
				}

				#if TMR_INFO_DEBUG == 1
				{
					printf ( "\r\n[TMR EVENT] tmr left %u, no tmr released\r\n", Timer.tmr_nbr );        
				}
				#endif  /* TMR_INFO_DEBUG */

			} 

			#if TMR_INFO_DEBUG == 1
			else
			{
				printf ( "\r\n[TMR EVENT] err tmr released***\r\n" );      
			}
			#endif  /* TMR_INFO_DEBUG */
		break;

		default:  break;
	}

	return false;
}


/*
 **********************************************************************************
 *	函 数 名: TMR_LowLevelIfInit
 *	功能说明: 定时器接口初始化
 *	形     参: 无
 *	返 回 值: 状态码
 **********************************************************************************
*/  
void TMR_LowLevelIfInit ( void )
{
	Tmr10msCounter = 0;	
	Tmr100msCounter = 0;
	memset ( ( uint8_t* )&Timer, 0, sizeof ( TMR_IfTypedef ) );
}


/*
 **********************************************************************************
 *	函 数 名: TMR_TickUpdateRequest
 *	功能说明: 定时器更新10ms处理，软定时器更新请求
 *            原型，以下10ms，100ms均参照此update
 *	形     参: 无
 *	返 回 值: 无
 **********************************************************************************
*/  
void TMR_TickUpdateRequest ( void )				
{
	uint32_t i;

	if ( Timer.tmr_nbr > 0 && Tmr10msCounter > 0 )
	{
		for ( i = 0; i < TMR_ID_COUNT; i++ )
		{
			if ( Timer.tmr_alloc[ i ].TimerId > 0 && Timer.tmr_alloc[ i ].TimerType == TMR_TYPE_TICK )
			{
				if ( Timer.tmr_count[ i ] <= 1 )
				{
					uint8_t TimerId = Timer.tmr_alloc[ i ].TimerId;

					if ( Timer.tmr_cyclic[ i ] == false )
					{
						#if OS_CRITICAL_METHOD == 3   	/* Allocate storage for CPU status register      */
							OS_CPU_SR  cpu_sr = 0;
						#endif
//						OS_ENTER_CRITICAL ();
						Timer.tmr_alloc[ i ].TimerId = 0;
						Timer.tmr_nbr--;
						Tmr10msCounter--;
//						OS_EXIT_CRITICAL ();
					}
					else
					{
						Timer.tmr_count[ i ] = Timer.tmr_alloc[ i ].TimerValue;
					}

					if ( Timer.tmr_alloc[ i ].TimerHdlr )
					{
						Timer.tmr_alloc[ i ].TimerHdlr ( TimerId );
					}
				} 
				else  
				{
					Timer.tmr_count[ i ]--;
				}          
			}
		} 
	}
}



/*
 **********************************************************************************
 *	函 数 名: TMR_10msUpdateRequest
 *	功能说明: 定时器更新10ms处理，软定时器更新请求，与上同
 * 			  TMR_TYPE_10MS时，直接在systick里做，其余地方与TMR_TYPE_10MS保持一致
 *	形 	  参: 无
 *	返 回 值: 无
 **********************************************************************************
*/ 
void TMR_10msUpdateRequest ( void )
{
	uint32_t i;

	if ( Timer.tmr_nbr > 0 && Tmr10msCounter > 0 )
	{
		for ( i = 0; i < TMR_ID_COUNT; i++ )
		{
			if ( Timer.tmr_alloc[ i ].TimerId > 0 && Timer.tmr_alloc[ i ].TimerType == TMR_TYPE_10MS )
			{
				if ( Timer.tmr_count[ i ] <= 1 )
				{
					uint8_t TimerId = Timer.tmr_alloc[ i ].TimerId;

					if ( Timer.tmr_cyclic[ i ] == false )
					{
						#if OS_CRITICAL_METHOD == 3 	/* Allocate storage for CPU status register      */
						OS_CPU_SR  cpu_sr = 0;
						#endif
//						OS_ENTER_CRITICAL ();
						Timer.tmr_alloc[ i ].TimerId = 0;
						Timer.tmr_nbr--;
						Tmr10msCounter--;
//						OS_EXIT_CRITICAL ();
					}
					else
					{
						Timer.tmr_count[ i ] = Timer.tmr_alloc[ i ].TimerValue;
					}

					if ( Timer.tmr_alloc[ i ].TimerHdlr )
					{
						Timer.tmr_alloc[ i ].TimerHdlr ( TimerId );
					}
				} 
				else  
				{
					Timer.tmr_count[ i ]--;
				}          
			}
		} 
	}
}


/*
 **********************************************************************************
 *	函 数 名: TMR_100msUpdateRequest
 *	功能说明: 定时器更新100ms处理，软定时器更新请求，与上同
 * 			  TMR_TYPE_100MS时，直接在systick里做，其余地方与TMR_TYPE_100MS保持一致
 *	形 	  参: 无
 *	返 回 值: 无
 **********************************************************************************
*/ 
void TMR_100msUpdateRequest ( void )
{
	uint32_t i;

	if ( Timer.tmr_nbr > 0 && Tmr100msCounter > 0 )
	{
		for ( i = 0; i < TMR_ID_COUNT; i++ )
		{
			if ( Timer.tmr_alloc[ i ].TimerId > 0 && Timer.tmr_alloc[ i ].TimerType == TMR_TYPE_100MS )
			{
				if ( Timer.tmr_count[ i ] <= 1 )
				{
					uint8_t TimerId = Timer.tmr_alloc[ i ].TimerId;

					if ( Timer.tmr_cyclic[ i ] == false )
					{
						#if OS_CRITICAL_METHOD == 3 	/* Allocate storage for CPU status register      */
						OS_CPU_SR  cpu_sr = 0;
						#endif
//						OS_ENTER_CRITICAL ();
						Timer.tmr_alloc[ i ].TimerId = 0;
						Timer.tmr_nbr--;
						Tmr100msCounter--;
//						OS_EXIT_CRITICAL ();
					}
					else
					{
						Timer.tmr_count[ i ] = Timer.tmr_alloc[ i ].TimerValue;
					}

					if ( Timer.tmr_alloc[ i ].TimerHdlr )
					{
						Timer.tmr_alloc[ i ].TimerHdlr ( TimerId );
					}
				} 
				else  
				{
					Timer.tmr_count[ i ]--;
				}          
			}
		} 
	}
}





